package com.fowo.api.pda.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fowo.api.common.model.DataIndex;
import com.fowo.api.common.model.PageSearchFilter;
import com.fowo.api.controller.purchase.vo.inventoryTurnoverVo;
import com.fowo.api.entity.WarehouseBin;
import com.fowo.api.inventory.entity.Inventory;
import com.fowo.api.inventory.mapper.InventoryMapper;
import com.fowo.api.inventory.model.*;
import com.fowo.api.inventory.model.form.InventoryExchangeFormVo;
import com.fowo.api.inventory.service.InventoryBusinessService;
import com.fowo.api.mapper.ProductMapper;
import com.fowo.api.mapper.WarehouseBinMapper;
import com.fowo.api.model.quality.QualityCheckInventoryVo;
import com.fowo.api.model.stock.in.StockInItemVo;
import com.fowo.api.model.stock.in.StockInVo;
import com.fowo.api.model.stock.in.product.StockInProductItemVo;
import com.fowo.api.model.stock.in.product.StockInProductSearchParamPo;
import com.fowo.api.model.stock.in.product.StockInProductVo;
import com.fowo.api.pda.mapper.PdaPutawayMapper;
import com.fowo.api.pda.model.PdaPutawayVo;
import com.fowo.api.pda.model.ProductInventoryVo;
import com.fowo.api.pda.model.PutawayParamPo;
import com.fowo.api.pda.model.PutawayVo;
import com.fowo.api.pda.service.PdaPutawayService;
import com.fowo.api.service.StockInProductService;
import com.fowo.api.user.model.JwtUserInfo;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class PdaPutawayServiceImpl implements PdaPutawayService {

    @Resource
    private PdaPutawayMapper pdaPutawayMapper;
    @Resource
    protected StockInProductService stockInProductService;
    @Resource
    private InventoryBusinessService inventoryBusinessService;
    @Resource
    private WarehouseBinMapper warehouseBinMapper;

    @Override
    public Page<PdaPutawayVo> pageSearch(PutawayParamPo search) {
        Page<PdaPutawayVo> page = this.pdaPutawayMapper.pageSearch(search.toPage(), search);
        List<PdaPutawayVo> records = page.getRecords();
        if(CollectionUtils.isNotEmpty(records)){
            for(PdaPutawayVo pdaPutaway : records){
                StockInProductSearchParamPo productListSearchParamPo = new StockInProductSearchParamPo();
                productListSearchParamPo.setParentStockInId(pdaPutaway.getId());
//                productListSearchParamPo.setWaitPutawayGt(0);
                productListSearchParamPo.setFinalFilters(new ArrayList<>());
                productListSearchParamPo.getFinalFilters().add(new PageSearchFilter()
                        .setDataIndex(new DataIndex("waitPutaway"))
                        .setOp("gt")
                        .setValue("0"));
                pdaPutaway.setProducts(stockInProductService.search(productListSearchParamPo));
            }
        }
        return page;
    }

    @Override
    public PdaPutawayVo getInfo(Long id){
        PdaPutawayVo pdaPutawayVo = pdaPutawayMapper.selectInfo(id);
        StockInProductSearchParamPo productListSearchParamPo = new StockInProductSearchParamPo();
        productListSearchParamPo.setParentStockInId(pdaPutawayVo.getId());
//        productListSearchParamPo.setWaitPutawayGt(0);
        productListSearchParamPo.setFinalFilters(new ArrayList<>());
        productListSearchParamPo.getFinalFilters().add(new PageSearchFilter()
                .setDataIndex(new DataIndex("waitPutaway"))
                .setOp("gt")
                .setValue("0"));
        pdaPutawayVo.setProducts(stockInProductService.search(productListSearchParamPo));
        return pdaPutawayVo;
    }

    @Override
    public StockInProductItemVo getProductItemVo(Long id,String sku){
        StockInProductSearchParamPo productListSearchParamPo = new StockInProductSearchParamPo();
        productListSearchParamPo.setParentStockInId(id);
        productListSearchParamPo.setSku(sku);
        return stockInProductService.search(productListSearchParamPo).get(0);
    }

    @Override
    public List<String> getRecommendBin(Long stockId ,String sku,Long shopId,String fnsku){
        return  pdaPutawayMapper.selectRecommendBin(stockId,sku,shopId,fnsku);
    }


    public List<WarehouseBin> getBinByWarehouse(Long stockId){
        List<String> types = new ArrayList<>();
        types.add("2");
        types.add("3");
        types.add("7");
        List<WarehouseBin> list = warehouseBinMapper.selectList(Wrappers.lambdaQuery(WarehouseBin.class)
                .eq(WarehouseBin::getWarehouseId,stockId)
                .in(WarehouseBin::getType,types));
        return list;
    }

    @Override
    public List<ProductInventoryVo> getProduct(Long binId, String sku) throws Exception {
        List<ProductInventoryVo> list = pdaPutawayMapper.selectProductInventoryVoBySku(binId,sku);
        return list;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void putaway(PutawayVo vo) throws Exception {
        WarehouseBin warehouseBin = warehouseBinMapper.selectOne(Wrappers.lambdaQuery(WarehouseBin.class)
                .eq(WarehouseBin::getWarehouseId,vo.getWid())
                .eq(WarehouseBin::getStorageBin,vo.getBin()));
        Assert.notNull(warehouseBin,"上架仓位不存在");
        vo.setToBinId(warehouseBin.getId());

        InventoryExchangeFormVo formVo = prepareInventoryTurnover(vo);
        inventoryBusinessService.exchange(formVo);

        if(null != vo.getId()){
            StockInProductVo voById = stockInProductService.getVoById(vo.getId());
            voById.setWaitPutaway(voById.getWaitPutaway()-vo.getQuantity());
            stockInProductService.update(voById);
        }
    }


    protected InventoryExchangeFormVo prepareInventoryTurnover(PutawayVo vo)
            throws Exception {
        JwtUserInfo jwtUserInfo = JwtUserInfo.fromHeader();

        InventoryExchangeFormVo formVo = new InventoryExchangeFormVo();
        formVo.setFrom(TargetTypeEnum.Normal);
        formVo.setTo(TargetTypeEnum.Normal);
        formVo.setFormNum(null);
        formVo.setFormOperator(jwtUserInfo.getUserId().toString());
        formVo.setFromStockId(vo.getWid());
        formVo.setToStockId(vo.getWid());
        formVo.setModel(PatternEnum.FIFO);
        formVo.setDocumentType("仓库转移");

        SimpleInventoryItem inventoryItem = new SimpleInventoryItem();
        inventoryItem.setId(vo.getProductId());
        InventoryExchangeVo exchangeItem = new InventoryExchangeVo();
        exchangeItem.setItem(inventoryItem);
        exchangeItem.setQty(BigDecimal.valueOf(vo.getQuantity()));
        exchangeItem.setShopId(
                String.valueOf(vo.getShopId()).equals("null")
                        ? null
                        : String.valueOf(vo.getShopId())
        );
        exchangeItem.setFnSku(
                String.valueOf(vo.getFnSku()).equals("null")
                        ? null
                        : String.valueOf(vo.getFnSku())
        );
        Map<Long, Integer> binIds = new HashMap<>();
        binIds.put(
                vo.getFromBinId(),
                Integer.parseInt(
                        String.valueOf(vo.getQuantity()).equals("null")
                                ? "0"
                                : String.valueOf(vo.getQuantity())
                )
        );
        exchangeItem.setFromBinIds(binIds);
        Map<Long, Integer> toBinIds = new HashMap<>();
        toBinIds.put(
                vo.getToBinId(),
                Integer.parseInt(
                        String.valueOf(vo.getQuantity()).equals("null")
                                ? "0"
                                : String.valueOf(vo.getQuantity())
                )
        );
        exchangeItem.setToBinIds(toBinIds);
        exchangeItem.setFromBinIdsType(TargetTypeEnum.Normal);
        exchangeItem.setToBinIdsType(TargetTypeEnum.Normal);
        exchangeItem.setCustomId(vo.getId());
        exchangeItem.setCustomBdId(null);
        formVo.add(exchangeItem);
        return formVo;
    }

}
